/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "Test.h"
#include "ImageData.h"
#include "DissociatedDipole.h"
#include "IntSamplesSet.h"
#include "Detector.h"
#include "ThrClassifier.h"

CTest::CTest()
{
	// Set the number of available tests
	m_NumTests=3;
}

CTest::~CTest()
{

}

void CTest::ShowResult(TEST_RESULT Result)
{

#ifdef _WIN32
	HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
	WORD wOldColorAttrs;
	CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 

	// Save the current color information
	GetConsoleScreenBufferInfo(h, &csbiInfo);
	wOldColorAttrs = csbiInfo.wAttributes; 
	
	// Begin the message
	printf ("\t[" );

	// Set the new color information depending on the result to show
	switch(Result)
	{
	case TEST_OK: // Successful test
		SetConsoleTextAttribute ( h, FOREGROUND_GREEN | FOREGROUND_INTENSITY );
		printf ("OK" );
		break;
	case TEST_FAIL: // The test has failed
		SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY );
		printf ("FAIL" );
		break;
	case TEST_LIB_EXCEPTION: // Exception thrown
		SetConsoleTextAttribute ( h, FOREGROUND_RED | FOREGROUND_INTENSITY | COMMON_LVB_REVERSE_VIDEO);
		printf ("EXCEPTION" );
		break;
	}

	// Restore the original colors
	SetConsoleTextAttribute ( h, wOldColorAttrs);

	// End the message
	printf ("]\n" );

#else

	// Begin the message
	printf ("\t[" );


	// Set the new color information depending on the result to show
	switch(Result)
	{
	case TEST_OK: // Successful test
		printf("%c[%d;%dmOK",0x1B,8,32);
		break;
	case TEST_FAIL: // The test has failed
		printf("%c[%d;%dmFAIL",0x1B,8,31);
		break;
	case TEST_LIB_EXCEPTION: // Exception thrown
		printf ("EXCEPTION" );
		break;
	}

	// Restore the original colors	
	printf ("%c[%dm",0x1B,0);

	// End the message
	printf ("]\n" );	
#endif
}

int CTest::GetNumTests(void)
{
	return m_NumTests;
}

void CTest::ShowGroupTestsTitle(string Title)
{
	printf("\n");
	printf("-----------------------------------------------------------------\n");
	printf("%s\n",Title.data());
	printf("-----------------------------------------------------------------\n");
}

void CTest::ShowTestTitle(string Title)
{
	printf("%-50s",Title.data());
}

void CTest::RunTest(int Idx)
{
	
	// Run the test
	switch(Idx)
	{
	case 0:
		ShowGroupTestsTitle("Test the dissociated dipoles");
		TestDipoles();
		break;
	case 1:
		ShowGroupTestsTitle("Test the object detector");
		//TestObjDetector();
		break;
	case 2:
		ShowGroupTestsTitle("Test the dissociated dipoles");
		//TestCascade();
		break;
	default:
		// Do nothing
		break;

	}	
}

bool CTest::TestDipoles(void)
{
	int i,j,k;
	int NumRounds=10;
	double SetParameters[15];
	double GetParameters[15];
	int SetNumPars,GetNumPars;
	double RndVal;
	bool Correct;
	char Title[512];	
	CDissociatedDipole oDipole;

	// The parameters vector must have the following format:
	//
	//  |--------------------------------------------------------------------------------------------------------
	//  |        Dipole1       |       Dipole2        || Polarity ||    Weights   ||    Rotated    || Channels  | 
	//  |--------------------------------------------------------------------------------------------------------
	//  | 0  1    2      3     | 4  5    6      7     ||    8     ||    9   10    ||    11   12    ||  13  14   |
	//  |--------------------------------------------------------------------------------------------------------
	//  | x  y  width  height  | x  y  width  height  ||  P [0,1] || W1  W2 [0,1] || R1   R2 [0,1] ||  C1  C2   |
	//  |--------------------------------------------------------------------------------------------------------
	//
	// In the case of Haar-like features, parameters are given as:
	//  |---------------------------------------------------------
	//  |        Dipole1       |       Type        || Polarity   |
	//  |---------------------------------------------------------
	//  | 0  1    2      3     |         4         ||    5       |
	//  |---------------------------------------------------------
	//  | x  y  width  height  |         T [0-7]   ||    P [0,1] |
	//  |---------------------------------------------------------

	/*
	Assign the parameters of a dipole and read them again to be sure that they are
	stored and recovered correctly.
	*/
	sprintf(Title,"Set/Get parameters of a Haar-like feature with %d parameters",5);
	ShowTestTitle(Title);
	try
	{
		// Select the number of parameters
		SetNumPars=5;

		// Generate random numbers for position and sizes
		for(i=0,Correct=true;i<NumRounds && Correct;i++)
		{
			// Generate the parameters
			for(j=0;j<4;j++)
			{
				// Store the random values for position and size
				RndVal=RAND_VALUE();
				SetParameters[j]=cvRound(RndVal*100);
			}
			// Store the random value for the type
			RndVal=RAND_VALUE();
			SetParameters[4]=cvRound(RndVal*7);

			// Set the parameters
			oDipole.SetParameters(SetNumPars,SetParameters);
			
			// Obtain the complete list of parameters
			GetNumPars=oDipole.GetNumParameters();
			oDipole.GetParameters(GetParameters);

			// Assign this complete list
			for(j=0;j<GetNumPars;j++)
				SetParameters[j]=cvRound(GetParameters[j]);
			oDipole.SetParameters(GetNumPars,SetParameters);

			// Compare the values
			oDipole.GetParameters(GetParameters);
			for(j=0;j<GetNumPars;j++)
			{
				if(SetParameters[j]!=cvRound(GetParameters[j]))
					Correct=false;
			}
		}

		// Show the result using the function ShowResult
		if(Correct)
			ShowResult(TEST_OK);
		else
			ShowResult(TEST_FAIL);
	}
	catch(Evolutive::CEvolutiveLibException &e)
	{
		ShowResult(TEST_LIB_EXCEPTION);
		cout << e.ToString() << endl;
	}

	// Repeat the test for each possible number of parameters
	for(k=0;k<5;k++)
	{
		// Set the number of parameters
		switch(k)
		{
			case 0:
				SetNumPars=8;
				break;
			case 1:
				SetNumPars=9;
				break;
			case 2:
				SetNumPars=11;
				break;
			case 3:
				SetNumPars=13;
				break;
			case 4:
				SetNumPars=15;
				break;
		}
		sprintf(Title,"Set/Get parameters of a dipole with %d parameters",SetNumPars);
		ShowTestTitle(Title);
		try
		{
			// Generate random numbers for position and sizes
			for(i=0,Correct=true;i<NumRounds && Correct;i++)
			{
				// Generate the parameters
				for(j=0;j<8;j++)
				{
					// Store the random values for position and size
					RndVal=RAND_VALUE();
					SetParameters[j]=cvRound(RndVal*100);
				}
				// Store a random value for the polarity
				if(SetNumPars>8)
				{
					RndVal=RAND_VALUE();
					SetParameters[8]=cvRound(RndVal);
				}
				// Store random values for the weights
				if(SetNumPars>9)
				{
					RndVal=RAND_VALUE();
					SetParameters[9]=cvRound(RndVal);
					RndVal=RAND_VALUE();
					SetParameters[10]=cvRound(RndVal);
				}
				// Store random values for the rotation
				if(SetNumPars>11)
				{
					RndVal=RAND_VALUE();
					SetParameters[11]=cvRound(RndVal);
					RndVal=RAND_VALUE();
					SetParameters[12]=cvRound(RndVal);
				}
				// Store random values for the channel
				if(SetNumPars>13)
				{
					RndVal=RAND_VALUE();
					SetParameters[13]=cvRound(RndVal);
					RndVal=RAND_VALUE();
					SetParameters[14]=cvRound(RndVal);
				}

				// Set the parameters
				oDipole.SetParameters(SetNumPars,SetParameters);

				// Obtain the complete list of parameters
				GetNumPars=oDipole.GetNumParameters();
				oDipole.GetParameters(GetParameters);

				// Assign this complete list
				for(j=0;j<GetNumPars;j++)
					SetParameters[j]=cvRound(GetParameters[j]);
				oDipole.SetParameters(GetNumPars,SetParameters);

				// Compare the values
				oDipole.GetParameters(GetParameters);
				for(j=0;j<GetNumPars;j++)
				{
					if(SetParameters[j]!=cvRound(GetParameters[j]))
						Correct=false;
				}
			}

			// Show the result using the function ShowResult
			if(Correct)
				ShowResult(TEST_OK);
			else
				ShowResult(TEST_FAIL);
		}
		catch(Evolutive::CEvolutiveLibException &e)
		{
			ShowResult(TEST_LIB_EXCEPTION);
			cout << e.ToString() << endl;
		}
	}

	/*
	An empty image is created, and two regions are defined into this image.
	Then a set of different types of dipoles are defined and their values 
	are compared with the expected ones.
	*/
	ShowTestTitle("Evaluation of a dissociated dipole with a synthetic image");
	try
	{
		// Define the parameters
		int W=100,H=300;
		int x1,y1,w1,h1,c1,x2,y2,w2,h2,c2;
		double V1,V2,DipVal,TVal;

		// Create two black images
		IplImage *Image=cvCreateImage(cvSize(W,H),IPL_DEPTH_8U,1);
		IplImage *AuxImage=cvCreateImage(cvSize(W,H),IPL_DEPTH_8U,1);
		cvSetZero(Image);

		// Generate two regions in the image
		RndVal=RAND_VALUE();
		x1=cvRound(RndVal*W/2.0);
		RndVal=RAND_VALUE();
		y1=cvRound(RndVal*H/2.0);
		RndVal=RAND_VALUE();
		w1=cvRound(RndVal*(W/2.0-x1)+5);
		RndVal=RAND_VALUE();
		h1=cvRound(RndVal*(H/2.0-y1)+5);
		RndVal=RAND_VALUE();
		c1=cvRound(RndVal*128)*2;
		RndVal=RAND_VALUE();
		x2=cvRound(RndVal*W/2.0+W/2.0);
		RndVal=RAND_VALUE();
		y2=cvRound(RndVal*H/2.0+H/2.0);
		RndVal=RAND_VALUE();
		w2=cvRound(RndVal*(W/2.0-x1)+5);
		RndVal=RAND_VALUE();
		h2=cvRound(RndVal*(H/2.0-y1)+5);
		RndVal=RAND_VALUE();
		c2=cvRound(RndVal*128)*2;

		// Correct the regions
		if(x1+w1>=W)
		{
			x1-=W-w1+1;
			if(x1<0)
			{
				w1-=abs(x1);
				x1=0;
			}
		}
		if(x2+w2>=W)
		{
			x2-=W-w2+1;
			if(x2<0)
			{
				w2-=abs(x2);
				x2=0;
			}
		}
		if(y1+h1>=H)
		{
			y1-=H-h1+1;
			if(y1<0)
			{
				h1-=abs(y1);
				y1=0;
			}
		}
		if(y2+h2>=H)
		{
			y2-=H-h2+1;
			if(y2<0)
			{
				h2-=abs(y2);
				y2=0;
			}
		}
		
		// Draw these regions to the final image
		cvSetZero(AuxImage);		
		cvRectangle(AuxImage,cvPoint(x1,y1),cvPoint(x1+w1-1,y1+h1-1),cvScalar(c1),CV_FILLED);
		cvAdd(Image,AuxImage,Image);
		cvSetZero(AuxImage);		
		cvRectangle(AuxImage,cvPoint(x2,y2),cvPoint(x2+w2-1,y2+h2-1),cvScalar(c2),CV_FILLED);
		cvAdd(Image,AuxImage,Image);

		// Create a dissociated dipole
		CDissociatedDipole DissDip;
		CImageData *ImgData=new CImageData(Image);
		DissDip.SetEvalType(DIPEVAL_SUM);
		SetParameters[0]=x1;
		SetParameters[1]=y1;
		SetParameters[2]=w1;
		SetParameters[3]=h1;
		SetParameters[4]=x2;
		SetParameters[5]=y2;
		SetParameters[6]=w2;
		SetParameters[7]=h2;
		DissDip.SetParameters(8,SetParameters);

		// Evaluate the theoretic region values
		V1=w1*h1*c1;
		V2=w2*h2*c2;
		
		// Evaluate the dipole with different parameters
		Correct=true;

		// Polarity change
		SetParameters[8]=0;
		DissDip.SetParameters(9,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=V1-V2;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;
		SetParameters[8]=1;
		DissDip.SetParameters(9,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=V2-V1;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;
		
		// Weights change
		SetParameters[8]=0;
		SetParameters[9]=0;
		SetParameters[10]=0;
		DissDip.SetParameters(11,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=V1-V2;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;
		SetParameters[8]=1;
		SetParameters[9]=0;
		SetParameters[10]=0;
		DissDip.SetParameters(11,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=V2-V1;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;
		SetParameters[8]=0;
		SetParameters[9]=1;
		SetParameters[10]=0;
		DissDip.SetParameters(11,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=2*V1-V2;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;
		SetParameters[8]=0;
		SetParameters[9]=1;
		SetParameters[10]=1;
		DissDip.SetParameters(11,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=2*V1-2*V2;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;
		SetParameters[8]=1;
		SetParameters[9]=1;
		SetParameters[10]=0;
		DissDip.SetParameters(11,SetParameters);
		DipVal=DissDip.Apply(ImgData);
		TVal=V2-2*V1;
		if(fabs(DipVal-TVal)>0.0001)
			Correct=false;

		// Release the image data
		delete ImgData;
		
		// Release the images
		//cvReleaseImage(&Image);
		cvReleaseImage(&AuxImage);

		// Show the result using the function ShowResult
		if(Correct)
			ShowResult(TEST_OK);
		else
			ShowResult(TEST_FAIL);	
	}
	catch(Evolutive::CEvolutiveLibException &e)
	{
		ShowResult(TEST_LIB_EXCEPTION);
		cout << e.ToString() << endl;
	}

	/*
	Load a background image and an object image. Paste the object in a random position and verify if the detector
	retrieves the same parameter values from both evaluation ways.
	*/
	ShowTestTitle("Evaluate Dissociated Dipoles (Sum,Mean)");

	try
	{
		bool Correct=false;
		CIntSamplesSet SmpSet;
		int incx=8,incy=10;

		// Open object images
		SmpSet.Load("../data/UIUC_Cars_01_Test.dat");

		// Load background image
		IplImage *ObjImg=cvLoadImage("../data/Image0005.bmp",0);
		IplImage *BgImg=cvCreateImage(cvSize(ObjImg->width+2*incx,ObjImg->height+2*incy),IPL_DEPTH_8U,1);

		// Paste the object image to the background image
		cvSetZero(BgImg);
		cvSetImageROI(BgImg,cvRect(incx,incy,ObjImg->width,ObjImg->height));
		cvCopyImage(ObjImg,BgImg);
		cvResetImageROI(BgImg);

		// Create a dipole
		CDissociatedDipole DissDip1,DissDip2;	
		double SetParameters[15];
		SetParameters[0]=10;
		SetParameters[1]=10;
		SetParameters[2]=6;
		SetParameters[3]=6;
		SetParameters[4]=20;
		SetParameters[5]=20;
		SetParameters[6]=6;
		SetParameters[7]=6;
		DissDip1.SetParameters(8,SetParameters);
		SetParameters[0]+=incx;
		SetParameters[1]+=incy;
		SetParameters[4]+=incx;
		SetParameters[5]+=incy;
		DissDip2.SetParameters(8,SetParameters);

		// Create the data structures for the images
		CData *BgImgData=new CImageData(BgImg);
		CData *ObjImgData=new CImageData(ObjImg);

		// Apply the dissociated dipole to the image
		DissDip1.SetEvalType(DIPEVAL_SUM);
		double DipValImg=DissDip1.Apply(ObjImgData);
		DissDip1.SetEvalType(DIPEVAL_MEAN);
		double DipValImg2=DissDip1.Apply(ObjImgData);

		DissDip2.SetEvalType(DIPEVAL_SUM);
		double DipValBg=DissDip2.Apply(BgImgData);
		DissDip2.SetEvalType(DIPEVAL_MEAN);
		double DipValBg2=DissDip2.Apply(BgImgData);

		// Change the scale of the detection
		cvSetZero(BgImg);
		cvSetImageROI(BgImg,cvRect(incx,incy,cvRound(static_cast<double>(ObjImg->width)/2.0),cvRound(static_cast<double>(ObjImg->height)/2.0)));
		cvResize(ObjImg,BgImg);
		cvResetImageROI(BgImg);

		SetParameters[0]=10;
		SetParameters[1]=10;
		SetParameters[4]=20;
		SetParameters[5]=20;
		for(int i=0;i<8;i++)
		{
			SetParameters[i]=cvRound(SetParameters[i]/2.0);
		}
		SetParameters[0]+=incx;
		SetParameters[1]+=incy;
		SetParameters[4]+=incx;
		SetParameters[5]+=incy;
		DissDip2.SetParameters(8,SetParameters);

		DissDip2.SetEvalType(DIPEVAL_SUM);
		double DipValBgScale=DissDip2.Apply(BgImgData);
		DissDip2.SetEvalType(DIPEVAL_MEAN);
		double DipValBgScale2=DissDip2.Apply(BgImgData);

		// Check the values
		Correct=true;
		if(fabs(DipValImg-DipValBg)>0.001 || fabs(DipValImg2-DipValBg2)>0.001)
			Correct=false;
		if(fabs(DipValBgScale2-DipValBg2)>0.1)
			Correct=false;

		// Remove images
		cvReleaseImage(&BgImg);
		cvReleaseImage(&ObjImg);

		// Show the result using the function ShowResult
		if(Correct)
			ShowResult(TEST_OK);
		else
			ShowResult(TEST_FAIL);
	}
	catch(Evolutive::CEvolutiveLibException &e)
	{
		ShowResult(TEST_LIB_EXCEPTION);
		cout << e.ToString() << endl;
	}

	return true;
}

bool CTest::TestObjDetector(void)
{
	bool Correct=false;
	CIntSamplesSet SmpSet;
	CDetector oDetector;
	CThrClassifier oClassifier;
	CDissociatedDipole oDipole;
	double Parameters[30];

	int incx=20,incy=30,Idx=5;

	// Select an image object from a sample set and paste it into a background.
	// Compare the results using the classifier over the sample, and the results of
	// a detector over the target region.
	ShowTestTitle(" Test description ");
	try
	{
		// Open object images
		SmpSet.Load("../data/UIUC_Cars_01_Test.dat");

		// Load background image
		IplImage *ObjImg=SmpSet.GetImage(Idx);
		IplImage *NegImg=cvCreateImage(cvGetSize(ObjImg),IPL_DEPTH_8U,1);
		IplImage *SmallImg=cvCreateImage(cvSize(0.5*ObjImg->width,0.5*ObjImg->height),IPL_DEPTH_8U,1);
		IplImage *BgImg=cvCreateImage(cvSize(3*ObjImg->width,3*ObjImg->height),IPL_DEPTH_8U,1);

		incx=cvRound((BgImg->width-ObjImg->width)/2.0);
		incy=cvRound((BgImg->height-ObjImg->height)/2.0);

		// Create a small copy of the object image and a negative sample
		cvResize(ObjImg,SmallImg);
		cvSetZero(NegImg);

		// Define a dissociated dipole
		bool CorrectDip=false;
		double DipVal=0;

		// Ex dip
		Parameters[0]=0;
		Parameters[1]=0;
		Parameters[2]=1;
		Parameters[3]=1;

		//In Dip
		Parameters[6]=1;		
		Parameters[7]=1;
		Parameters[4]=ObjImg->width-Parameters[6]-1;
		Parameters[5]=ObjImg->height-Parameters[7]-1;
		
		// Polarity		
		Parameters[8]=0;

		while(!CorrectDip)
		{
			Parameters[2]++;
			Parameters[3]++;
			Parameters[6]++;		
			Parameters[7]++;
			Parameters[4]=ObjImg->width-Parameters[6]-1;
			Parameters[5]=ObjImg->height-Parameters[7]-1;
			oDipole.SetParameters(9,Parameters);

			// Get the dipole value over the image
			DipVal=oDipole.Apply(SmpSet.GetData(Idx));

			// If we obtain a value larger than 2 consider the dipole as correct
			if(fabs(DipVal)>2)
				CorrectDip=true;
		}

		// Adjust the dipole polarity to obtain a positive value
		if(DipVal<0)
		{
			Parameters[8]=1;
			oDipole.SetParameters(9,Parameters);
			DipVal=oDipole.Apply(SmpSet.GetData(Idx));
		}

		// From now, we consider the test correct if no error is produced
		Correct=true;

		// Set a classifier with just one feature
		oClassifier.SetThrEqualValueAction(EQTHR_NEG);
		oClassifier.SetSize(ObjImg->width,ObjImg->height);
		oClassifier.SetFeature(&oDipole);		

		// Test the classifier over the image
		if(oClassifier.Apply(SmpSet.GetData(Idx))!=1)
			Correct=false;

		// Create the detector
		oDetector.SetMinScale(1.0);
		oDetector.SetMaxScale(1.0);		
		oDetector.SetClassifier(&oClassifier);

		// Check the result of the detector over the object and a black region
		if(oDetector.GetClass(ObjImg)<0 || oDetector.GetClass(NegImg)>0)
			Correct=false;

		// Create the composed image for the original object
		cvSetZero(BgImg);
		cvSetImageROI(BgImg,cvRect(incx,incy,ObjImg->width,ObjImg->height));
		cvCopyImage(ObjImg,BgImg);
		cvSet(BgImg,cvScalar(255));
		cvResetImageROI(BgImg);

		// Detect the objects in the composed image
		CRectVector oRectVector;
		oRectVector.clear();
		oDetector.ShowRegions(&oRectVector,BgImg);
		oDetector.FindRegions(&oRectVector,BgImg);
		oDetector.ShowRegions(&oRectVector,BgImg);

		// Create the composed image for the resized object
		cvSetZero(BgImg);
		cvSetImageROI(BgImg,cvRect(incx,incy,SmallImg->width,SmallImg->height));
		cvCopyImage(SmallImg,BgImg);
		cvSet(BgImg,cvScalar(255));
		cvResetImageROI(BgImg);

		cout << "test";
printf("PRRRRRROOOOOVAAA");
		// Detect the objects in the composed image
		oDetector.SetMinScale(0.5);
		oDetector.SetMaxScale(0.5);		
		oRectVector.clear();
		oDetector.ShowRegions(&oRectVector,BgImg);
		oDetector.FindRegions(&oRectVector,BgImg);
		oDetector.ShowRegions(&oRectVector,BgImg);
		
		// Create a black image with just two diffrent (only few valid positions
		cvSetZero(BgImg);
		cvSetImageROI(BgImg,cvRect(incx+Parameters[0],incy+Parameters[1],Parameters[2],Parameters[3]));
		cvSet(BgImg,cvScalar(100));
		cvResetImageROI(BgImg);
		cvSetImageROI(BgImg,cvRect(incx+Parameters[4],incy+Parameters[5],Parameters[6],Parameters[7]));
		cvSet(BgImg,cvScalar(200));
		cvResetImageROI(BgImg);
		
		// Detect the objects in the composed image
		oRectVector.clear();
		oDetector.ShowRegions(&oRectVector,BgImg);
		oDetector.FindRegions(&oRectVector,BgImg);
		oDetector.ShowRegions(&oRectVector,BgImg);

		// Show the result using the function ShowResult
		if(Correct)
			ShowResult(TEST_OK);
		else
			ShowResult(TEST_FAIL);	
	}
	catch(Evolutive::CEvolutiveLibException &e)
	{
		ShowResult(TEST_LIB_EXCEPTION);
		cout << e.ToString() << endl;
	}
	
	return true;
}

bool CTest::TestCascade(void)
{
	bool Correct=false;

	// Test A
	ShowTestTitle(" Test description ");
	try
	{
		//TODO: Code of the test


		// Show the result using the function ShowResult
		if(Correct)
			ShowResult(TEST_OK);
		else
			ShowResult(TEST_FAIL);	
	}
	catch(Evolutive::CEvolutiveLibException &e)
	{
		Correct=false;
		ShowResult(TEST_LIB_EXCEPTION);
		cout << e.ToString() << endl;
	}

	return Correct;
}
/*   Test function pattern
bool CTest::TextXXX(void)
{
	bool Correct=false;

	// Test A
	ShowTestTitle(" Test description ");
	try
	{
		//TODO: Code of the test


		// Show the result using the function ShowResult
		if(Correct)
			ShowResult(TEST_OK);
		else
			ShowResult(TEST_FAIL);	
	}
	catch(Evolutive::CEvolutiveLibException &e)
	{
		Correct=false;
		ShowResult(TEST_LIB_EXCEPTION);
		cout << e.ToString() << endl;
	}

	return Correct;
}
*/
